# Load files into local sesame server
# run "load3account.py -h" for more info 
__version__ = "$Id$"
import os
import sys
import logging
import StringIO
import ConfigParser
from optparse import OptionParser
from httplib import BadStatusLine
import rdflib
from rdflib import plugin

plugin.register(
    'sparql', rdflib.query.Processor,
    'rdfextras.sparql.processor', 'Processor')
plugin.register(
    'sparql', rdflib.query.Result,
    'rdfextras.sparql.query', 'SPARQLQueryResult')

from rdflib.graph import ConjunctiveGraph
from semprog import pysesame
from imports.loadRDF import loadGraph2Server, loadFile2Server
from imports import ofx2n3
from imports import bll_portfolio_position
from imports import bll_portfolio_activity
from imports import bll_checking
from imports import citina_portfolio_position, citina_portfolio_activity
from imports import pdf1
from imports import ofx2flt
from imports import flt2n3
from imports import directnet_checking

bank_modules={
        'ofx':ofx2flt,
        'OFX':ofx2flt,
        'qfx':ofx2flt,
        'QFX':ofx2flt,
        'ofx2rdf':ofx2n3,
        'bllpp':bll_portfolio_position,
        'bllpt':bll_portfolio_activity,
        'bllchck':bll_checking,
        'citipp':citina_portfolio_position,
        'citipt':citina_portfolio_activity,
        'pdf1':pdf1,
        'flt':flt2n3,
        'dc':directnet_checking,
}


usage = "usage: %prog [options] [input-file]*"
description="""load bank statement files into Sesame server.
The format of the bank statement is determined by the '-f' ('--format') option
or, if not given, by the input file's extension. To get more help on a specific
format type "%prog -f <format> help".
The following formats are currently supported:
RDF file, not just banking
('xml' for RDF/XML, 'notation3', 'trix', 'n3', 'nt', 'rdfa'),
OFX v1.0.2 ('ofx', 'qfx'),
Bank Leumi portfolio position in Excel file ('bllpp')
"""
parser = OptionParser(usage=usage,
                      description=description,
                      version=__version__)
parser.add_option("-u", "--url",
        dest="url",default="http://localhost:8080/openrdf-sesame",
        help="""Send output to Sesame server URL or a file-name.
Default http://localhost:8080/openrdf-sesame""")
parser.add_option("-f", "--format", dest="format",default=None,
                  help="""Input format. For help type "-f <fmt> help".
By default use file extension.
Supported values:
'xml' (for RDF/XML), 'notation3', 'trix', 'n3', 'nt', 'rdfa', 'owl'
"""+", ".join(bank_modules.keys())
   )
parser.add_option("-S", "--config", dest="cfg",default=None,
                  help="Read/Write hash convertion from a config file")
parser.add_option("-s", "--sha1",
                  action="store_true", dest="hashing",
                  help="Hash senstive fields")
parser.add_option("-x", "--extend", dest="ext",default=None,
                  help="""Supply one or more tag=value pairs to be used in the
import process. For example -x ACCTID=A1, -x DTASOF=20091121 or
-x "ACCTID=A1 DTASOF=20091121"
""")
parser.add_option("-v", "--verbose",
                  action="store_true", dest="verbose")
parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose")
(options, args) = parser.parse_args()

if options.verbose:
    logging.basicConfig(level=logging.INFO)
else:
    logging.basicConfig(level=logging.WARNING)

if options.cfg:
    options.hashing=ConfigParser.RawConfigParser()
    options.hashing.optionxform = str # options are case sensitive
    options.hashing.read(options.cfg)

# parse the flt line extension to be added to each line.
if options.ext:
    fltparams=flt2n3.parse(options.ext)
else:
    fltparams=None

for fname in args:
    logging.info("Loading "+fname+" to "+options.url)
    try:
        basename,ext = os.path.splitext(os.path.basename(fname))
        if ext.startswith('.'): ext=ext[1:]
        if options.format:
            format = options.format
        else:
            format = ext
        if format in ['xml', 'notation3', 'trix', 'n3', 'nt', 'rdfa', 'owl']:
            if fname=="help":
                print >>sys.stderr,"Any RDF file"
                continue
            if format=='owl':
                format = 'xml'
            if not options.url.startswith("http://"):
                pass
            else:
                loadFile2Server(fname,options.url,format,basename)
        elif format in bank_modules:
            module=bank_modules[format]
            module.fltparams=fltparams
            if fname=="help":
                if hasattr(module, 'help'):
                    print >>sys.stderr,module.help
                else:
                    print >>sys.stderr,module.__doc__
                continue
            try:
                if hasattr(module, 'pre') and callable(module.pre):
                    tmpfile=StringIO.StringIO()
                    logging.info('%s','converting to temp file in memory')
                    module.pre(fname,tmpfile,options.hashing)
                    tmpfile.seek(0)
                    fname=tmpfile
                outf = StringIO.StringIO()
                module.flat(fname,outf,"/"+basename,options.hashing)
            except IOError, e:
                logging.error("I/O Error converting %s to flat N3: %s" % (fname, e))
            except Exception, e:
                logging.error("I/O Error converting %s to flat N3: %s" % (fname, e))
            except:
                logging.error("Error converting %s to flat N3" % (fname))
            else:
                outf.seek(0)
                if options.url == "null":
                    pass
                elif not options.url.startswith("http://"):
                    fp = open(options.url,"w")
                    fp.write(outf.read())
                    fp.close
                else:
                    loadFile2Server(outf,options.url,"n3",basename)
        else:
            logging.error("Unknwon file extension "+ext)
    except IOError, e:
        if hasattr(e, 'reason'):
            logging.error('We failed to reach a server.')
            logging.error('Reason: '+str(e.reason))
        elif hasattr(e, 'code'):
            if e.code != 204:
                logging.error('The server couldn\'t fulfill the request.')
                logging.error('Error code: %s'%e.code)
    except BadStatusLine, e:
        logging.error("Bad status line"+e.line)
    except Exception , e:
        if options.verbose:
            logging.error("Exception %s"%e)
        else:
            logging.error("Exception")
if options.cfg:
    with open(options.cfg, 'wb') as cfgFp: options.hashing.write(cfgFp)
